package org.xin.security.controller;

import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.Api;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.xin.common.config.pojo.bo.ClientServer;
import org.xin.common.constant.Constants;
import org.xin.common.result.Result;
import org.xin.common.util.XinUtil;
import org.xin.common.config.RedisCache;
import org.xin.security.pojo.bo.SecurityUser;
import org.xin.security.component.UserOnlineComponent;
import org.xin.security.pojo.bo.UserOnline;

import java.util.*;

/**
 * @author ：xin
 * @date ：Created in 2021/10/3
 * @desc <p> 缓存监控 </p>
 * @modified By：$
 * @version: $
 */
@Api(tags = "缓存监控")
@CrossOrigin
@Controller
@RequestMapping("/monitor")
public class MonitorController {
    @Autowired
    private RedisTemplate<String, String> redisTemplate;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private UserOnlineComponent userOnlineComponent;

    //    @PreAuthorize("@ss.hasPermi('monitor:cache:list')")
    @GetMapping("cache")
    public Result getCacheInfo() throws Exception {
        Properties info = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info());
        Properties commandStats = (Properties) redisTemplate.execute((RedisCallback<Object>) connection -> connection.info("commandstats"));
        Object dbSize = redisTemplate.execute((RedisCallback<Object>) connection -> connection.dbSize());

        Map<String, Object> result = new HashMap<>(3);
        result.put("info", info);
        result.put("dbSize", dbSize);

        List<Map<String, String>> pieList = new ArrayList<>();
        commandStats.stringPropertyNames().forEach(key -> {
            Map<String, String> data = new HashMap<>(2);
            String property = commandStats.getProperty(key);
            data.put("name", StrUtil.removeAll(key, "cmdstat_"));
            data.put("value", StrUtil.subBetween(property, "calls=", ",usec"));
            pieList.add(data);
        });
        result.put("commandStats", pieList);
        return Result.success(result);
    }

//    @PreAuthorize("@ss.hasPermi('monitor:server:list')")
    /*@GetMapping("server")
    public Result getInfo() throws Exception {
        Server server = new Server();
        server.copyTo();
        return AjaxResult.success(server);
    }*/

    //    @PreAuthorize("@ss.hasPermi('monitor:online:list')")
    @GetMapping("online/list")
    public Result list(String ipaddr, String userName) {
        Collection<String> keys = redisCache.keys(Constants.LOGIN_TOKEN_KEY + "*");
        List<UserOnline> userOnlineList = new ArrayList<>();
        for (String key : keys) {
            SecurityUser user = redisCache.getCacheObject(key);
            if (XinUtil.noNull(ipaddr) && XinUtil.noNull(userName)) {
                if (XinUtil.equal(ipaddr, user.getIpaddr()) && XinUtil.equal(userName, user.getUsername())) {
                    userOnlineList.add(userOnlineComponent.selectOnlineByInfo(ipaddr, userName, user));
                }
            } else if (XinUtil.noNull(ipaddr)) {
                if (XinUtil.equal(ipaddr, user.getIpaddr())) {
                    userOnlineList.add(userOnlineComponent.selectOnlineByIpaddr(ipaddr, user));
                }
            } else if (XinUtil.noNull(userName) && XinUtil.noNull(user.getUser())) {
                if (XinUtil.equal(userName, user.getUsername())) {
                    userOnlineList.add(userOnlineComponent.selectOnlineByUserName(userName, user));
                }
            } else {
                userOnlineList.add(userOnlineComponent.loginUserToUserOnline(user));
            }
        }
        Collections.reverse(userOnlineList);
        userOnlineList.removeAll(Collections.singleton(null));
        return Result.success(userOnlineList);
    }

    /**
     * 强退用户
     */
//    @PreAuthorize("@ss.hasPermi('monitor:online:forceLogout')")
//    @Log(title = "在线用户", businessType = BusinessType.FORCE)
    @DeleteMapping("online/{tokenId}")
    public Result forceLogout(@PathVariable String tokenId) {
        redisCache.deleteObject(Constants.LOGIN_TOKEN_KEY + tokenId);
        return Result.ok();
    }


//    @PreAuthorize("@ss.hasPermi('monitor:server:list')")
    @GetMapping("server")
    public Result getClientServerInfo() throws Exception {
        ClientServer server = new ClientServer();
        server.copyTo();
        return Result.success(server);
    }
}
